/*
 * Date         Author      Note
 * 2015.04.13   wzwz        新探针功能
 * 2015.04.13   wzwz        纱嘴起始位置
 * 2015.04.13   wzwz        行定问题
 * 2015.04.14   wzwz        暂停提示
 * 2015.04.24   wzwz        恒强的兔子与乌龟
 * 2015.05.25   wzwz        行定执行完后执行节约
 * 2015.05.25   wzwz        机头在编织区域的位置bug
 * 2015.05.27   wzwz        增加副程式
 * 2015.06.25   wzwz        矫正续片右边纱嘴号
 * 2015.06.25   wzwz        增加卸片特征值
 * 2015.07.07   wzwz        自动行定落布复位几次的bug
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mh/common.h>
#include <mh/sram.h>
#include <mh/mac.h>
#include "knit.h"
#include <mh/mh_file.h>
#include "prefixknit.h"
#include "backpiece.h"
#include "compress.h"
#include "translator.h"
#include "pthread.h"

#define MH_FILE_SYNC()               sync()
#define MH_CYCLE_NUM               100

#define SYS_STATE_READY     1
#define SYS_STATE_RESET     2
#define SYS_STATE_KNIT      3
#define SYS_STATE_HALT      4
#define SYS_STATE_PK        5
//
enum { BAR_STOPPOS = 0, BAR_SLOWPOS, BAR_QUICKPOS, BAR_NONE };
/*
 *
 */
int IsStopLineValid(MH_KNIT *p)
{
    return p->knit_state.stop_line;
}
/*
 * set state of machine
 * param state: run/test/reset/halt/pk
 */
int SetSysState(MH_KNIT *p, int state)
{
    int ret = 0;
    if(p->machine_ok)
    {
        if(p->communication == COMM_SRAM)
        {
            ret = SramSendState(p->pmac, state);
        }
        else
        {
            ret = MacSendState(p->pmac, state);
        }
    }
    return ret;
}
/*
 *
 */
void ForbidFeedback(MH_KNIT *p, int enable)
{
    p->knit_state.forbid_feedback = enable;
}
/*
 * check task finished
 */
int IsTaskFinished(MH_KNIT *p)
{
    return p->done_cloth >= p->total_cloth;
}
/*
 * get how many extent pieces
 */
uint GetPieceNum(MH_KNIT *p)
{
    int i = 1;
    uint ret = 0;
    for(i = 1; i < sizeof(p->ext_piece_enable); ++i)
    {
        if(p->ext_piece_enable[i])
        {
            ++ret;
        }
    }
    return ret;
}
/*
 * get direction of yarn from row
 * param pcon: pointer to control pages not be null
 * param start: start line
 * param end: end line
 * param pdrt: pointer to which to fill needed data and sizeof which is 16
 *             (1-on the left, 2-on the right)
 */
void GetAllYarnStartDrt(MH_KNIT *p, PKNIT_PAGE pcon, ushort start, ushort end, uchar *pdrt)
{
    int i = 0;
    for(i = start - 1; i < end; ++i)
    {
        int gauze1 = pcon[i].gauze1_1;
        gauze1 <<= 8;
        gauze1 |= (pcon[i].gauze1_9 & 0xFF);
        int gauze2 = pcon[i].gauze2_1;
        gauze2 <<= 8;
        gauze2 |= pcon[i].gauze2_9;
        int g = 0;
        for(g = 0; g < 16; ++g)
        {
            if(!pdrt[g])
            {
                if(p->sys_info.cam == 1)
                {
                     if((0x8000 >> g) & gauze1)
                    {
                        pdrt[g] = 1;
                    }
                }
                else
                {
                     if((0x8000 >> g) & gauze1)
                    {
                        pdrt[g] = (i & 1) + 1;
                    }
                    else if((0x8000 >> g) & gauze2)
                    {
                        pdrt[g] = (i & 1) + 1;
                    }
                }
            }
        }
    }
}
/*
 * get start position of yarn
 * param data: filled with 16 gauze of short
 * param start_line: start line based from 1
 */
int GetYarnStartPos(MH_KNIT *p, short *data, int start_line)
{
    memset(data, 0, sizeof(short) * 16);
    KNIT_PAGE *con = p->knit_page_head;
    int i = 0, j = 0;
    short init[16] = {0};
    enum {LEFT = 1, RIGHT = 2};
    /* 起底纱嘴 */
    if(p->scissor_enable || p->board_enable)
    {
        uchar yarn = p->board_param.gauze;
        if(yarn >= 1 && yarn <= GAUZE_NUM)
        {
            if(data[yarn - 1] == 0)
            {
                data[yarn - 1] = LEFT;
            }
        }
    }
    //
    if(con && start_line <= p->total_line)
    {
        for(i = start_line; i <= p->total_line; ++i)
        {
            ushort gauze1 = con[i].gauze1_1;
            gauze1 <<= 8;
            gauze1 |= con[i].gauze1_9 & 0xFF;
            ushort gauze2 = con[i].gauze2_1;
            gauze2 <<= 8;
            gauze2 |= con[i].gauze2_9 & 0xFF;
            ushort gauze3 = con[i].gauze3_1;
            gauze3 <<= 8;
            gauze3 |= con[i].gauze3_9;
            ushort gauze4 = con[i].gauze4_1;
            gauze4 <<= 8;
            gauze4 |= con[i].gauze4_9;
#if(MH_SYS_CAM == 1)
             ushort gauze = gauze1;
#else
            ushort gauze = gauze1 | gauze2 | gauze3 | gauze4;
#endif
            for(j = 0; j < 16; ++j)
            {
                if(!init[j])
                {
                    if((0x8000 >> j) & gauze)
                    {
                        init[j] = (i & 1) ? LEFT : RIGHT;
                    }
                }
            }
        }
        for(i = 1; i < start_line; ++i)
        {
            ushort gauze1 = con[i].gauze1_1;
            gauze1 <<= 8;
            gauze1 |= con[i].gauze1_9 & 0xFF;
            ushort gauze2 = con[i].gauze2_1;
            gauze2 <<= 8;
            gauze2 |= con[i].gauze2_9 & 0xFF;
            ushort gauze3 = con[i].gauze3_1;
            gauze3 <<= 8;
            gauze3 |= con[i].gauze3_9;
            ushort gauze4 = con[i].gauze4_1;
            gauze4 <<= 8;
            gauze4 |= con[i].gauze4_9;
#if(MH_SYS_CAM == 1)
             ushort gauze = gauze1;
#else
            ushort gauze = gauze1 | gauze2 | gauze3 | gauze4;
#endif
            for(j = 0; j < 16; ++j)
            {
                if(!init[j])
                {
                    if((0x8000 >> j) & gauze)
                    {
                        init[j] = (i & 1) ? LEFT : RIGHT;
                    }
                }
            }
        }
    }
    //exchange yarn
    for(j = 0; j < 16; ++j)
    {
        if(init[j])
        {
            if(p->gauze_exchange[0][j] && p->gauze_exchange[0][j] != j + 1)
            {
                printf("ext0: %d, %d, %d\n", j, p->gauze_exchange[0][j], init[j]);
                if(!data[p->gauze_exchange[0][j] - 1])
                {
                    data[p->gauze_exchange[0][j] - 1] = init[j];
                }
            }
            else
            {
                if(!data[j])
                {
                    data[j] = init[j];
                }
            }
            if(p->gauze_exchange[1][j] && p->gauze_exchange[1][j] != j + 1)
            {
                printf("ext1: %d, %d, %d\n", j, p->gauze_exchange[1][j], init[j]);
                if(!data[p->gauze_exchange[1][j] - 1])
                {
                    data[p->gauze_exchange[1][j] - 1] = init[j];
                }
            }
            printf("init: %d, %d, %d\n", j, data[j], init[j]);
        }
    }

    if(p->board_enable || p->scissor_enable)
    {
        int left = GetYarnLeftOutStop(p);
        int right = GetYarnRightOutStop(p);
        for(i = 0; i < p->sys_info.gauze; ++i)
        {
            if(data[i] == LEFT)//to right
            {
                data[i] = -left - p->yarn_out.stop[0][i];
            }
            else if(data[i] == RIGHT)//to left
            {
                data[i] = p->total_needle + right + p->yarn_out.stop[1][i];
            }
            else
            {
                data[i] = 0;
            }
        }
    }
    else
    {
        int n = p->start_needle;
        int width = p->flower_width;
        int total_needle = p->total_needle;
        if(p->ext_piece_num > 1)
        {
            uchar src[16] = {0};
            int inter = p->ext_piece_inter;
            for(i = 0; i < 16; ++i)
            {
                if(data[i] == LEFT)//to right
                {
                    init[i] = n;
                    src[i] = TRUE;
                }
                else if(data[i] == RIGHT)//to left
                {
                    init[i] = n + width;
                    src[i] = TRUE;
                }
                else
                {
                    init[i] = 0;
                    src[i] = FALSE;
                }
                printf("data1: %d, %d, %d, %d\n", i, data[i], init[i], n);
            }
            for(i = 0; i < 8; ++i)
            {
                if(p->ext_piece_enable[i + 1])
                {
                    for(j = 0; j < 16; ++j)
                    {
                        uchar g = p->ext_piece_yarn[i + 1][j];
                        if(g >= 11 && g <= 18)
                        {
                            g -= 2;
                        }
                        if(data[j] && g && src[i])
                        {
                            init[g - 1] = init[j] + (width + inter) * (i + 1);
                            data[g - 1] = data[j];
                        }
                    }
                }
                printf("data: %d, %d, %d\n", i, data[i], init[i]);
            }
        }
        else
        {
            for(i = 0; i < 16; ++i)
            {
                if(data[i] == LEFT)//to right
                {
                    init[i] = 1;
                }
                else if(data[i] == RIGHT)//to left
                {
                    init[i] = total_needle;
                }
                else
                {
                    init[i] = 0;
                }
                printf("data: %d, %d, %d\n", i, data[i], init[i]);
            }
        }
        for(i = 0; i < 16; ++i)
        {
            if(data[i] == LEFT)
            {
                data[i] = init[i] - p->yarn_stop[0][0][i];
            }
            else if(data[i] == RIGHT)
            {
                data[i] = init[i] + p->yarn_stop[1][0][i];
            }
        }
    }
    return 0;
}
/*
 * breif: 获取纱嘴实际的起始位置
 * @data[out]: 纱嘴停放位置
 * @line: start from 1
 *
 */
void GetYarnRealPos(MH_KNIT *p, short *data, int line)
{
    int gsp[GAUZE_NUM] = { 0 };
    int i = 0;
    if(line > 0)
    {
        --line;
    }
    else
    {
        line = 0;
    }

    translator_get_gauze_pos(p, line, gsp);
    /////////////////////////////////////////////////////////
    for(i= 0; i < GAUZE_NUM; i++)
    {
        printf("%d ", gsp[i]);
    }printf("\n");
    //////////////////////////////////////////////////////////
    printf("p->sys_info.gauze:%d\n",p->sys_info.gauze);
    for(i = 0; i < GAUZE_NUM; ++i)
    {
        data[i] = 0;
        if(gsp[i] != INVALID_GAUZE_POS)
        {
            data[i] = gsp[i];
        }
    }
}
/*
 * 判断是否需要打行定，当前行数超过起始行数２０行，并且正身没有摇结束，就不需要打行定，直接落布
 * @param row 当前行数，从１开始
 */
int IsNeedLoop(MH_KNIT *p, ushort row)
{
    int i = 0;
    int bp_start = backpiece_get_start_row(p);
    int knit_row = 0;
    int start_row = 0;

    if((p->need_loop & LOOP_BRY_BIT) ||
        (p->need_loop & LOOP_FRY_BIT))
    {
        return FALSE;
    }

    if(!p->knit_page || !p->total_line)
    {
        return FALSE;
    }

    if((bp_start > 0) && (row > bp_start))
    {
        /* 后片 */
        if(row - bp_start < 20)
        {
            return TRUE;
        }
        start_row = bp_start;
    }
    else
    {
        /* 前片 */
        if(row < 20)
        {
            return TRUE;
        }
        start_row = 1;
    }

    if((start_row >= 1) && (start_row <= p->total_line) &&
        (row >= 1) && (row <= p->total_line))
    {
        for(i = start_row - 1; i < row; i++)
        {
            KNIT_PAGE *pcon = &p->knit_page[i];
            if (pcon->gauze1_1 || pcon->gauze1_9 ||
                pcon->gauze2_1 || pcon->gauze2_9)
            {
                if ((pcon->code_1FA & 0x7F) || (pcon->code_1BA & 0x7F) ||
                    pcon->code_1FH || pcon->code_1BH ||
                    (pcon->code_2FA & 0x7F) || (pcon->code_2BA & 0x7F) ||
                    pcon->code_2FH || pcon->code_2BH)
                {
                    knit_row++;
                }
            }
        }
    }

    if (knit_row < 20)
    {
        return TRUE;
    }

    return FALSE;
}
/*
 *
 */
void GetLoopMode(MH_KNIT *p)
{
    p->need_loop &= ~LOOP_YC_BIT;
    p->need_loop &= ~LOOP_NL_BIT;
    p->need_loop |= p->need_loop_record;

    printf("MM_RESET: need_loop = %x\n", p->need_loop);
    if(!p->knit_state.prefix)
    {
        uchar src_dir[GAUZE_NUM] = { 0 };
        GetAllYarnStartDrt(p, p->knit_page, 1, p->total_line, src_dir);
        uchar des_dir[GAUZE_NUM] = { 0 };
        ushort end = p->curt_line + 2;
        /* 编织没有完成，该行不计 */
        if((p->need_loop & LOOP_KC_BIT) == KNIT_PREARE ||
            ((p->need_loop & LOOP_KC_BIT) == KNITING))
        {
            --end;
        }
        GetAllYarnStartDrt(p, p->knit_page, end, p->total_line, des_dir);
        /* 纱嘴没有回到原始位置 */
        int i = 0;
        for(i = 0; i < GAUZE_NUM; ++i)
        {
            if(des_dir[i] && des_dir[i] != src_dir[i])
            {
                printf("yc bit\n");
                p->need_loop |= LOOP_YC_BIT;
                break;
            }
        }
        if (IsNeedLoop(p, p->curt_line + 1))
        {
            p->need_loop |= LOOP_NL_BIT;
            printf("need loop bit\n");
        }
    }
#if 0
    if((p->need_loop & LOOP_SY_BIT) ||
        ((p->need_loop & LOOP_KC_BIT) == KNITING) ||
        (p->need_loop & LOOP_YC_BIT))
    {
        p->need_loop |= LOOP_NL_BIT;
    }
#endif
    printf("MM_RESET2: p->need_loop = %x\n", p->need_loop);
}
/*
 *
 */
 static void HangDingInit(MH_KNIT *p, ushort times)
 {
     p->hangding_start = HD_START;
     p->hangding_end = HD_END;
     p->hangding_times = times;
 }
//////////////////////////////////////////////////////////////////////////////////
//
static int CheckWidth(MH_KNIT *p)
{
    int ret = 0;
    int total = p->total_needle;
    int width = p->flower_width;
    int real_width = p->right_bound - p->left_bound + 1;  //不包括带纱嘴符号
    int total_width = width;
    if(p->ext_piece_num)
    {
        int inter = p->ext_piece_inter;
        int i = 0;
        int start = width + inter;
        for(i = 0; i < 8; i++)
        {
            if(p->ext_piece_enable[i + 1])
            {
                total_width = start + width;
            }
            start += width + inter;
        }
    }
    if(!p->header_type.enable || p->header_type.left_forbid || p->header_type.right_forbid)
    {
        total_width += (p->inch_type / (MM_PER_INCH * 10)) * p->mac_header_inter;
    }
    int n = p->start_needle;
    //不包括左右两边带纱嘴的符号
    if(n + total_width - 1 - (width - real_width) > total)
    {
        ret = -1;
    }
    printf("check width: %d, %d, %d, %d, %d\n", n, total_width, width, real_width, total);
    return ret;
}
/*
 * line: start from 1
 */
static void GetEconomyData(MH_KNIT *p)
{
    int i = 0;
    ushort line = p->curt_line + 1;
    ushort endline = p->total_line;
    if(p->knit_state.fp_enable)
    {
        endline = p->backpiece_start_line - 1;
    }
    for(i = 0; i < endline; ++i)
    {
        KNIT_PAGE *q = &p->knit_page[i];
        if(q)
        {
            if(q->economy_start == line && q->economy_end <= endline && q->economy_num)
            {
                ECONOMY_LIST *k = calloc(1, sizeof(ECONOMY_LIST));
                k->next = p->peco_list;
                p->peco_list = k;
                k->node.start = line;
                k->node.end = q->economy_end;
                k->node.num = q->economy_num;
                p->economy_left = k->node.num;
                p->economy_times = p->economy_left;
                printf("economy1: %d, %d, %d\n", p->economy_left, line, q->economy_end);
                break;
            }
        }
    }
}
/*
 * set hang ding
 */
int LockHangDing(MH_KNIT *p)
{
    if(p->communication == COMM_SRAM)
    {
        p->knit_state.prefix = FALSE;
        if(!SetRunThreadState(p, TH_STATE_PAUSE))
        {
            if(p->economy_left > 0 || p->curt_line + 1 != p->hangding_end)
            {
                p->hangding_enable = HD_START;
                if(p->company == COMPANY_HQ)
                {
                    p->knit_state.hd_forever = TRUE;
                }
                p->economy_left = p->hangding_times;
                p->economy_times = p->economy_left;
                if(!p->economy_left && p->curt_line + 2 == p->hangding_end)
                {
                    int prefix = FALSE;
                    int aux_index = -1;
                    ushort next_line = GetNextLine(p, p->curt_line + 1, &prefix, &aux_index);
                    int next_prefix = prefix;
                    int next_aux_index = aux_index;
                    //printf("hangding: %d, %d, %d\n", next_line, GetNextLine(p, next_line, FALSE), p->sram_need_send);
                    GetNormalKnitData(p, p->sram_send_data, GetNextLine(p, next_line, &prefix, &aux_index), prefix, aux_index);
                    GetChangedParam(p, p->sram_send_data, next_line, next_prefix, next_aux_index);
                    p->sram_send_data[2] = p->curt_line + 1;
                    p->sram_send_data[3] = (p->curt_line + 1) >> 8;
                    if(SramSendKnitData(p->pmac, p->sram_send_data, sizeof(p->sram_send_data)))
                    {
                        p->sram_need_send = TRUE;
                    }
                    //printf("hangding: %d, %d, %d\n", next_line, GetNextLine(p, next_line, FALSE), p->sram_need_send);
                }
            }
            if(SetRunThreadState(p, TH_STATE_RUN) < 0)
            {
                printf("hangding error\n");
                return ERROR_KNIT_THREAD;
            }
        }
    }
    else
    {
        if(MacLockRow(p->pmac, p->hangding_start, p->hangding_end, p->hangding_times))
        {
            return ERROR_LOCK_ROW;
        }
        else
        {
            p->economy_left = p->hangding_times;
            p->economy_times = p->economy_left;
            p->hangding_enable = HD_START;
        }
    }
    return 0;
}
/*
 * reset machine
 */
int ResetMachine(MH_KNIT *p, int start_line, int type)
{
    MAC_RESET mac_reset;
    mac_reset.start_line = start_line;
    mac_reset.type = 0;

    if(type != RESET_GOTO && type != RESET_DROP)
    {
        GetLoopMode(p);
    }
    p->curt_line = start_line - 1;
    p->error_code = 0;
    p->aux_list.index = -1;
    p->hangding_enable = 0;
    p->knit_state.hd_wait = 0;
    if(p->knit_state.bp_enable)
    {
        p->hangding_start = p->backpiece_start_line - 1 + p->hd_start_base;
        p->hangding_end = p->backpiece_start_line - 1 + p->hd_end_base;
    }
    else
    {
        HangDingInit(p, MH_CYCLE_NUM);   //set hangding init param ;
    }
    if(!strlen(p->file_name))
    {
        return ERROR_NO_KNIT_FILE;
    }
    if(!p->flower_width)
    {
        return ERROR_FLOWER_WIDTH;
    }
    else if(CheckWidth(p))
    {
        SwitchRedLight(p->pmac, TRUE);
        return ERROR_EXCEED_WIDTH;
    }
    if(!p->flower_height)
    {
        return ERROR_FLOWER_HEIGHT;
    }
    if(!p->total_line)
    {
        return ERROR_CONTROL_HEIGHT;
    }
    if(GetPieceNum(p) > 1 && p->board_enable)
    {
        return ERROR_BOARD_AGAINST_EXTENT_PIECE;
    }
    if(IsTaskFinished(p))
    {
        return ERROR_TASK_FINISHED;
    }

    /*prefix knit*/
    p->need_loop |= LOOP_AUTO_HD;
    printf("pk clear\n");
    pk_clear_data(p);
    if(p->board_enable)
    {
        /* 自动起底 */
        if(pk_init_data(p, start_line, PK_AUTO_BOARD, FALSE) > 0)
        {
            p->knit_state.reset_finished = FALSE;
            return ERROR_BOARD_START;
        }
    }
    else if((type == RESET_NORMAL) || (type == RESET_HD))
    {
        /* 自动落布 */
        if(p->knit_state.auto_hd_drop/* && (p->auto_drop_flag == AUTO_DROP_FLAG)*/)
        {
            pk_init_data(p, start_line, PK_AUTO_HD_DROP, (type == RESET_HD));
            if(p->pk_data.pcnt.rows > 0)
            {
                pk_convert_economy(p);
            }
        }
    }
    else if(type == RESET_DROP)
    {
        printf("refixknit knit_start:%d,  knit_end:%d, flowet width:%d\n",p->knit_start, p->knit_end, p->flower_width);
        /* 卸片 */
        pk_init_data(p, 1, PK_AUTO_DROP, FALSE);
        p->knit_state.drop_cloth = TRUE;
    }
    else
    {
        p->knit_state.drop_cloth = FALSE;
    }
    printf("prefix rows = %d\n", p->pk_data.pcnt.rows);

    if(p->pk_data.pcnt.rows > 0)
    {
        if(type != RESET_GOTO)
        {
            p->curt_line = 0;
            p->knit_state.prefix = TRUE;
        }
        //p->need_loop = 0;
        mac_reset.type = TRUE;
        if(p->communication == COMM_INET)
        {
            if(MacSendPkCon(p->pmac, p->pk_data.pcnt.buf, p->pk_data.pcnt.rows, p->pk_data.type) < 0)
            {
               return RUN_ERROR_NET;
            }
            if(MacSendPkDat(p->pmac, p->pk_data.ppat.buf, p->pk_data.pat_width, p->pk_data.ppat.rows) < 0)
            {
               return RUN_ERROR_NET;
            }
        }
    }
    else
    {
        p->knit_state.prefix = FALSE;
    }
    printf("type = %d\n",type);
    /* 复位之后有手动行定就不执行自动行定 */
    if(type == RESET_HD)
    {
        p->need_loop = 0;
    }

    while(p->peco_list)
    {
        ECONOMY_LIST *q = p->peco_list;
        p->peco_list = q->next;
        FREE(q);
    }
    printf("type = %d\n",type);
    p->economy_left = 0;
    p->economy_times = 0;
    GetEconomyData(p);
    //////////////////////////
    p->knit_state.take_yarn_mode = 1;
    ///////////////////////////
    if(p->knit_state.take_yarn_mode)
    {
        GetYarnRealPos(p, mac_reset.yarn_init_pos, start_line);
    }
    else
    {
        GetYarnStartPos(p, mac_reset.yarn_init_pos, start_line);
    }
    if(p->communication == COMM_SRAM)
    {
        uchar data[SEND_MAX_SIZE];
        GetNormalKnitData(p, data, start_line, p->knit_state.prefix, p->aux_list.index);
        data[2] = start_line;
        data[3] = start_line >> 8;
        int i = 0, j = 0;
        for(i = 0, j = 0; i < 8; i++, j+=2)
        {
            data[94 + j] = mac_reset.yarn_init_pos[i];
            data[95 + j] = mac_reset.yarn_init_pos[i] >> 8;
            //printf("yarn: %d, %d\n", mac_reset.yarn_init_pos[i], mac_reset.yarn_init_pos[i + 8]);
            data[ARM2DSP_GAUZE9_STOPL + 8 + j] = mac_reset.yarn_init_pos[i + 8];
            data[ARM2DSP_GAUZE9_STOPH + 8 + j] = mac_reset.yarn_init_pos[i + 8] >> 8;
        }
        data[80] = p->front_sink_reset_value;
        data[81] = p->front_sink_reset_value >> 8;
        data[82] = p->back_sink_reset_value;
        data[83] = p->back_sink_reset_value >> 8;
        int reset_type = SRAM_RESET_START;
        if(type == RESET_GOTO)
        {
            reset_type = SRAM_RESET_GOTO;
        }
        else if(type == RESET_DROP)
        {
            reset_type = SRAM_RESET_DROP;
        }
        if(SramStartMachine(p->pmac, data, sizeof(data), reset_type))
        {
            return ERROR_STATE_RESET;
        }
    }
    else
    {
        if(MacStartMachine(p->pmac, &mac_reset))
        {
            return ERROR_STATE_RESET;
        }
    }
    p->knit_state.reset_finished = FALSE;
    p->knit_state.process = KNIT_PROCESS_NONE;
    p->mac_speed_switch = STATE_RUN_SLOW;//禁止再次按复位对话框
    p->knit_count_time = 0;
    if(type == RESET_HD)
    {
        p->hangding_enable = HD_START;
        if(p->company == COMPANY_HQ)
        {
            p->knit_state.hd_forever = TRUE;
        }
        if(start_line == p->hangding_start)
        {
            p->economy_start = p->hangding_start;
            p->economy_end = p->hangding_end;
            p->economy_left = p->hangding_times;
            p->economy_times = p->hangding_times;
            LockHangDing(p);
        }
        else
        {
            p->economy_left = 0;
            p->economy_times = 0;
        }
    }
    return ERROR_KNIT_OK;
}
/*
 * hang ding
 */
int HangDing(MH_KNIT *p)
{
    printf("执行行定enable:%d\n",p->hangding_enable);
    if(p->board_enable)
    {
        return ERROR_BOARD_ENABLE;
    }
 /*   if(!p->knit_state.reset_finished)
    {
        p->knit_state.prefix = FALSE;
        p->knit_state.hd_wait = !p->knit_state.hd_wait;
        return RUN_FB_RESET_WAIT;
    }*/
    if(p->hangding_enable == HD_END)
    {
        HangDingInit(p, FALSE);
        return LockHangDing(p);
    }
    else if(p->hangding_enable == HD_FORBID_MODIFY)
    {
        if(p->economy_left > 0 || p->curt_line + 1 != p->hangding_end)
        {
            return LockHangDing(p);
        }
    }
    else if(p->hangding_enable == HD_START)
    {
        if(p->communication == COMM_SRAM)
        {
            p->hangding_enable = HD_FORBID_MODIFY;
            p->knit_state.hd_forever = FALSE;
            p->economy_left = 2;
        }
        else
        {
            HangDingInit(p, MH_CYCLE_NUM);
            LockHangDing(p);
        }
    }
    else
    {
        if(p->curt_line + 1 >= p->hangding_end)
        {
            p->hangding_enable = HD_END;
        }
        else
        {
            return LockHangDing(p);
        }
    }
    return 0;
}
/*
 * take on/off yarn
 */
int SwitchYarn(MH_KNIT *p)
{
    int ret = 0;
    if(p->machine_ok)
    {
        if(p->communication)
        {
            p->sram_send_data[ARM2DSP_STOP_BYTE] = p->yarn_up ? ARM2DSP_YARN_DOWN : ARM2DSP_YARN_UP;
            p->sram_need_send = TRUE;
        }
        else
        {
            p->yarn_up = !p->yarn_up;
            ret = MacSwitchYarn(p->pmac, !p->yarn_up);
        }
    }
    return ret;
}
/*
 * LockCloth
 */
int LockCloth(MH_KNIT *p)
{
    int ret = 0;
    p->piece_lock = !p->piece_lock;
    if(p->communication == COMM_SRAM)
    {
        RunChangeParam(p);
    }
    else
    {
        ret = MacSendPieceLock(p->pmac, p->piece_lock);
    }
    return ret;
}
/*
 * switch speed
 */
int SwitchSpeed(MH_KNIT *p)
{
    int ret = 0;
    if(p->gui_speed_type == SPEED_HIGH)
    {
        p->gui_speed_type = SPEED_LOW;
    }
    else
    {
        p->gui_speed_type = SPEED_HIGH;
    }
    if(p->communication == COMM_SRAM)
    {
        RunChangeParam(p);
    }
    else
    {
        ret = MacSendMacSpeed(p->pmac, p->gui_speed_type);
    }
    return ret;
}
/*
 * switch speed
 */
void  SetSpeedState(MH_KNIT *p, uchar state)
{
    p->gui_speed_type = state;
}
/*
 * get state of running: stop, slow, quick
 */
int GetRunState(MH_KNIT *p)
{
    return p->mac_speed_switch;
}
/*
 *
 */
void RunChangeParam(MH_KNIT *p)
{
    p->param_change = TRUE;
}
/*
 *
 */
int KnitRabOnStop(MH_KNIT *p, int speed)
{
    int ret= 0;
    if(p->machine_ok)
    {
        if(p->communication == COMM_SRAM)
        {
            if(speed < 0)
            {
                speed = -GetHighRollerFrequency(p, -speed);
            }
            else
            {
                speed = GetHighRollerFrequency(p, speed);
            }
            PSEND_LINE psend = (PSEND_LINE)p->sram_send_data;
            psend->high_roller_speed = speed;
            psend->opcode.rab_run = TRUE;
            p->sram_need_send = TRUE;
            //if(!SramSendKnitData(p->pmac, p->sram_send_data, sizeof(p->sram_send_data)));

        }
    }
    return ret;
}
/*
 * get next run line
 * param line: start from 1
 * ret: start from 1
 */
int GetNextLine(MH_KNIT *p, int line, int *prefix, int *aux_index)
{
    ushort economy_start = 0;
    ushort economy_end = 0;
    if(p->peco_list)
    {
        economy_start = p->peco_list->node.start;
        economy_end = p->peco_list->node.end;
    }
    if(p->knit_state.drop_cloth)
    {
        return line == 1 ? 2 : 1;
    }
    else if(*prefix)
    {
        if(line == p->pk_data.pcnt.rows)
        {
            *prefix = FALSE;
            if(p->knit_state.bp_enable)
            {
                return p->backpiece_start_line;
            }
            else
            {
                return 1;
            }
        }
        else
        {
            return line + 1;
        }
    }
    else if(*aux_index > -1)
    {
        if(line + 1 < p->aux_list.paux_con[*aux_index].rows)
        {
            return line + 1;
        }
        else
        {
            *aux_index = -1;
            return p->curt_line + 1;
        }
    }
    if(p->hangding_enable == HD_START || p->hangding_enable == HD_FORBID_MODIFY)
    {
        if(line == p->hangding_end)
        {
            return p->hangding_start;
        }
    }
    if(p->economy_left > 0 && /*p->*/economy_end == line)
    {
        return /*p->*/economy_start;
    }
    int endline = p->total_line;
    if(p->knit_state.fp_enable)
    {
        endline = p->backpiece_start_line - 1;
    }
    if(line == endline)
    {
        if(p->board_enable)
        {
            *prefix = TRUE;
            return 1;
        }
        else if(p->knit_state.bp_enable)
        {
            if (p->done_cloth + 1 >= p->total_cloth)
            {
                return 1;
            }
            else
            {
                return p->backpiece_start_line;
            }
        }
        else
        {
            return 1;
        }
    }
    *aux_index = GetAuxConIndex(p, line);
    if(*aux_index > -1)
    {
        return 1;
    }
    return line + 1;
}
/*
 * switch run line
 */
int SwitchRunLine(MH_KNIT *p)
{
    //printf("economy: %d, %d, %d\n", p->economy_left, p->knit_state.prefix, p->curt_line);
    if(p->knit_state.drop_cloth)
    {
        p->curt_line = !p->curt_line;
    }
    else if(p->knit_state.prefix)
    {
        if(p->curt_line + 1 == p->pk_data.pcnt.rows)
        {
            if(p->knit_state.bp_enable)
            {
                p->curt_line = p->backpiece_start_line - 1;
            }
            else
            {
                p->curt_line = 0;
            }
            p->knit_state.prefix = FALSE;
        }
        else
        {
            ++p->curt_line;
        }
    }
    else if(p->hangding_enable == HD_START || p->hangding_enable == HD_FORBID_MODIFY)
    {
        if(p->curt_line + 1 == p->hangding_end)
        {
            p->curt_line = p->hangding_start - 1;
            if(!p->knit_state.hd_forever)
            {
                --p->economy_left;
            }
            if(!p->economy_left)
            {
                p->hangding_enable = HD_END;
                if(p->peco_list)
                {
                    if(p->peco_list->node.end == p->hangding_end)
                    {
                        p->economy_left = p->peco_list->node.num;
                        p->economy_times = p->peco_list->node.num;
                    }
                }
            }
            else if(p->economy_left == 2)
            {
                p->hangding_enable = HD_FORBID_MODIFY;
            }
        }
        else
        {
            ++p->curt_line;
            if(p->curt_line + 1 == p->hangding_start && !p->economy_left)
            {
                p->economy_left = p->hangding_times;
            }
        }
    }
    else if(p->economy_left)
    {
        ushort economy_start = 0;
        ushort economy_end = 0;
        if(p->peco_list)
        {
            economy_start = p->peco_list->node.start;
            economy_end = p->peco_list->node.end;
        }
        //printf("economy: %d, %d, %d\n", p->economy_left, economy_start, economy_end);
        if(p->curt_line + 1 == /*p->*/economy_end)
        {
            p->curt_line = /*p->*/economy_start - 1;
            --p->economy_left;
            if(p->peco_list)
            {
                --p->peco_list->node.num;
                if(p->peco_list->node.num == 0)
                {
                    ECONOMY_LIST *q = p->peco_list;
                    p->peco_list = q->next;
                    free(q);
                    if(p->peco_list)
                    {
                        p->economy_left = p->peco_list->node.num;
                        p->economy_times = p->economy_left;
                    }
                }
            }
        }
        else
        {
            ++p->curt_line;
            GetEconomyData(p);
        }
    }
    else if(p->aux_list.index > -1 && p->aux_list.index < p->aux_list.num)
    {
        if(p->aux_list.line + 1 < p->aux_list.paux_con[p->aux_list.index].rows)
        {
            ++p->aux_list.line;
        }
        else
        {
            p->aux_list.index = -1;
            GetEconomyData(p);
        }
    }
    else
    {
        int endline = p->total_line;
        if(p->knit_state.fp_enable)
        {
            endline = p->backpiece_start_line - 1;
        }
        if(p->curt_line + 1 == endline)
        {
            if(p->board_enable)
            {
                p->curt_line = 0;
                p->knit_state.prefix = TRUE;
            }
            else if(p->knit_state.bp_enable)
            {
                p->curt_line = p->backpiece_start_line - 1;
            }
            else
            {
                p->curt_line = 0;
            }
            ++p->done_cloth;
            if(p->done_cloth == p->total_cloth)
            {
                if(p->knit_state.bp_enable || p->knit_state.fp_enable)
                {
                    p->total_cloth = p->total_cloth_backup;
                    p->done_cloth = p->done_cloth_backup;
                    p->knit_state.bp_enable = FALSE;
                    p->knit_state.fp_enable = FALSE;
                    p->curt_line = 0;
                }
            }
            p->knit_time = p->knit_count_time;
            p->knit_count_time = 0;
        }
        else
        {
            ++p->curt_line;
        }
        p->aux_list.index = GetAuxConIndex(p, p->curt_line);
        if(p->aux_list.index > -1)
        {
            p->aux_list.line = 0;
        }
        else
        {
            GetEconomyData(p);
        }
    }
    if(!p->economy_left)
    {
        p->economy_times = 0;
    }
    return p->curt_line;
}
/*
 * get data to send for run
 */
void GetChangedParam(MH_KNIT *p, uchar *data, ushort next_line, int prefix, int aux_index)
{
    uchar tmp[SEND_MAX_SIZE] = { 0 };
    GetNormalKnitData(p, tmp, next_line, prefix, aux_index);
    memcpy(&data[ARM2DSP_CHANGABLE_BYTE1], &tmp[ARM2DSP_CHANGABLE_BYTE1],
            ARM2DSP_CHNAGABLE_SIZE1);
    memcpy(&data[ARM2DSP_CHANGABLE_BYTE2], &tmp[ARM2DSP_CHANGABLE_BYTE2],
            ARM2DSP_CHANGABLE_SIZE2);
    memcpy(&data[ARM2DSP_CHANGABLE_BYTE3], &tmp[ARM2DSP_CHANGABLE_BYTE3],
            ARM2DSP_CHNAGABLE_SIZE3);
    ushort endline = p->total_line;
    if(p->knit_state.fp_enable)
    {
        endline = p->backpiece_start_line - 1;
    }
    //printf("%d, %d, %d\n", p->economy_left, p->knit_state.prefix, p->piece_lock);
    if(p->curt_line + 1 == endline && !p->economy_left && !p->knit_state.prefix
            && !(p->aux_list.index > -1 && p->aux_list.index < p->aux_list.num))
    {
        if(p->done_cloth + 1 == p->total_cloth)
        {
            if(p->knit_state.fp_enable || p->knit_state.bp_enable)
            {
                if (p->done_cloth_backup >= p->total_cloth_backup)
                {
                    data[ARM2DSP_STOP_BYTE] |= ARM2DSP_STOP_BIT;
                }
            }
            else
            {
                data[ARM2DSP_STOP_BYTE] |= ARM2DSP_STOP_BIT;
            }
        }
        if(p->piece_lock)
        {
            data[ARM2DSP_STOP_BYTE] |= ARM2DSP_STOP_BIT;
        }
        if(p->auto_zero_cloth && !((p->done_cloth + 1) % p->auto_zero_cloth))
        {
            data[ARM2DSP_STOP_BYTE] |= ARM2DSP_ZERO_BIT;
        }
    }
    if(next_line == p->stop_line && p->knit_state.stop_line && !p->knit_state.prefix
            && !(p->aux_list.index > -1 && p->aux_list.index < p->aux_list.num))
    {
        data[ARM2DSP_STOP_BYTE] |= ARM2DSP_STOPLINE_BIT;
    }
}
/*
 * 换行时，记录已经编织的范围
 */
void BackupKnitedRange(MH_KNIT *p)
{
    PAT_RANGE range = { 0 };
    backpiece_get_pattern_range(p, p->curt_line + 1, &range);
    p->knit_start = range.pat_start;
    p->knit_end = range.pat_end;
    p->sp = p->start_needle - p->left_bound;
}
/*
 *
 */
int GetRunFeedback(MH_KNIT *p, RUN_FEEDBACK *pfeed_back)
{
    int ret = 0;
    if(p->communication == COMM_SRAM)
    {
        //**太多删掉了，需要的话去之前版本拷贝
    }
    else
    {
        ret = MacGetRunFeedback(p->pmac, pfeed_back);
        if(ret >= 0)
        {
            /*换行*/
            if(p->curt_line + 1 != pfeed_back->row)
            {
                if(!p->knit_state.prefix && p->knit_state.reset_finished)
                {
                    BackupKnitedRange(p);
                    p->need_loop = 0;
                    p->need_loop_record = 0;
                }

                if((pfeed_back->row == GetKnitStartLine(p)) && (p->curt_line + 1 == GetKnitEndLine(p)))
                {
                    p->knit_time = p->knit_count_time;
                    p->knit_time = p->knit_count_time;
                }
                p->curt_line = pfeed_back->row - 1;
            }

            p->done_cloth = pfeed_back->cloth_finished;
            p->knit_state.drt = pfeed_back->mm_state >> 7;
            p->economy_left = pfeed_back->cycle_times;
            p->economy_start = pfeed_back->cycle_start;
            p->economy_end =  pfeed_back->cycle_end;
            p->bar_state = pfeed_back->bar_state;

            switch (pfeed_back->errcode)
            {
            case RUN_FB_SLOW_STATE:
                p->mac_speed_switch = STATE_RUN_SLOW;
                break;
            case RUN_FB_QUICK_STATE:
                p->mac_speed_switch = STATE_RUN;
                if(!p->knit_state.reset_finished)
                {
                    p->mac_speed_switch = STATE_RUN_SLOW;
                }
                break;
            default:
                break;
            }

            switch (pfeed_back->mm_state & 0x03)
            {
            case 0:
            case 3:
                p->mac_speed_switch = STATE_STOP;
                break;
            default:
                break;
            }

            if(!p->knit_state.prefix && p->knit_state.reset_finished)
            {
                if(pfeed_back->errcode == RUN_FB_LEFTSHA_WARN ||
                    pfeed_back->errcode == RUN_FB_RIGHTSHA_WARN)
                {
                    p->need_loop_record |= LOOP_SY_BIT;
                }
                p->need_loop_record &= ~LOOP_KC_BIT;
                p->need_loop_record |= 0x01 << ((pfeed_back->bar_state & 0x0C) >> 2);
            }
            usleep(10000);
            /*判断复位或前缀编织有没有完成*/
            if(p->knit_state.prefix || !p->knit_state.reset_finished)
            {
                ushort state = 0;
                ushort reset_state = 0;
                if(MacGetSysState(p->pmac, &state, &reset_state) < 0)
                {
                    usleep(20000);
                }
                else
                {
                    p->run_state = state;
                    p->run_reset_state = reset_state;
                    if(state == SYS_STATE_KNIT)
                    {
                        p->knit_state.prefix = FALSE;
                        p->knit_state.reset_finished = TRUE;
                        p->knit_state.process = KNIT_PROCESS_NORMAL_RUN;
                    }
                    else if(state == SYS_STATE_PK)
                    {
                        p->knit_state.prefix = TRUE;
                        p->knit_state.reset_finished = TRUE;
                        p->knit_state.process = KNIT_PROCESS_NORMAL_RUN;
                    }
                }
            }
        }
    }
    return ret;
}
/*
 * knit run thread
 */
void *RunMonitor(void *arg)
{
    MH_KNIT *p = (MH_KNIT*)arg;
    int ret = 0;
    RUN_FEEDBACK run_fb;
    while(p->th_request != TH_STATE_EXIT)
    {
        //printf("run thread: %d, %d\n", p->th_request, p->th_state);
        if(p->th_request == TH_STATE_PAUSE)
        {
            p->th_state = TH_STATE_PAUSE;
            usleep(50000);
            continue;
        }

        p->th_state = TH_STATE_RUN;

        memset(&run_fb, 0, sizeof(run_fb));
        ret = GetRunFeedback(p, &run_fb);
        if(ret < 0)
        {
            usleep(20000);
            continue;
        }
   //     printf("hd: %d, %d, %d, %d\n", p->hangding_enable, p->hangding_times, p->economy_times, p->economy_left);
        memcpy(&p->run_feedback, &run_fb, sizeof(RUN_FEEDBACK));
        if(p->run_feedback.errcode == RUN_FB_RESET_FINISHED)
        {
            //这个错误码一闪而过，延时是为了让窗口的线程捕捉得到
            usleep(100000);
        }
        else if(p->run_feedback.errcode == RUN_FB_UPS_SAVE_OK)
        {
            sleep(30);
        }
    }

    p->th_state = TH_STATE_EXIT;
    pthread_exit(0);

}
/*
 *
 */
int AllowKnitRun(MH_KNIT *p)
{
    int ret = 0;
    if(p->communication == COMM_SRAM)
    {
        PSEND_LINE psend = (PSEND_LINE) p->sram_send_data;
        psend->forbid.allow = TRUE;
        //p->sram_send_data[92] |= 0x04;

        if(SramSendKnitData(p->pmac, p->sram_send_data, sizeof(p->sram_send_data)))
        {
            p->sram_need_send = TRUE;
        }
    }
    return ret;
}
/*
 * set state of running thread(pause thread th_run)
 */
int SetRunThreadState(MH_KNIT *p, int state)
{
    int i = 0;
    p->th_request = state;
    for(i = 0; i < 500; i++)
    {
        if(p->th_state == state)
        {
            return 0;
        }
        usleep(2000);
    }
    return -1;
}
/*
 *
 */
int SwitchToKnitState(MH_KNIT *p, int enable)
{
    int ret = 0;
    if(!p->th_run)
    {
        pthread_create(&p->th_run, NULL, RunMonitor, p);
    }
    if(!p->th_run)
    {
        return -1;
    }
    if(enable)
    {
        ret = SetSysState(p, SYS_STATE_KNIT);
        if(!ret)
        {
            if(p->knit_state.process == KNIT_PROCESS_NORMAL_RUN)
            {
                p->param_change = TRUE;
            }
            ret = SetRunThreadState(p, TH_STATE_RUN);
        }
    }
    else
    {
        if(p->th_request == TH_STATE_RUN)
        {
            if(PowerOff(p))
            {
                AddSysLog(p, LOG_TYPE_RUN_FEEDBACK, RUN_FB_UPS_SAVE_NO);
            }
            WriteSysLogFile(SYS_LOG_FILE, &p->log_list);
            MH_FILE_SYNC();
        }
        ret = SetSysState(p, SYS_STATE_READY);
        if(!ret)
        {
            ret = SetRunThreadState(p, TH_STATE_PAUSE);
        }
    }
    return ret;
}
/*
 *
 */
int EndKnitRun(MH_KNIT *p)
{
    if(p->th_run)
    {
        p->th_request = TH_STATE_EXIT;
        pthread_join(p->th_run, NULL);
    }
    return 0;
}
